package top.yamhk.agent.entity;

import cn.hutool.core.net.NetUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import top.yamhk.agent.entity.dto.AnyKernel;
import top.yamhk.agent.entity.dto.Message;
import top.yamhk.agent.entity.enums.MatrixNodeType;
import top.yamhk.agent.utils.JsonUtils;

import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.Socket;

/**

 * @date 2019/4/12 22:37
 */
@Slf4j
@Getter
@Setter
@Accessors(chain = true)
@EqualsAndHashCode(of = {"clientIpOfProxy", "clientIpOfLocal", "username"}, callSuper = false)
public class KernelNode extends AnyKernel implements Serializable {
    /**
     * base
     */
    private volatile boolean online = true;
    private String contentOfRpcReq = "";
    private String contentOfRpcRes = "";
    private String remark = "default";
    private String content;
    /**
     * socket-transient-gsonIgnore
     */
    @JsonIgnore
    private transient Socket serverSocket;
    @JsonIgnore
    private transient PrintWriter printWriter;
    @JsonIgnore
    private transient BufferedReader bufferedReader;
    /**
     * 同以下内容
     * 登录相关> .上线时间.下线时间.登录终端.登录状态.登录次数（其他）
     */
    private String username = "";
    private String nickname = "";
    private String password;
    private String nodeType;
    /**
     * 昵称-头像-邮箱-手机-身份?地址
     */
    private String mid;
    private String avatar;
    private String signature;
    private String email;
    private String phoneNumber;
    private String address;
    /**
     * 服务器属性
     */
    private String serverIp;
    private String serverName;
    private String serverCharset;
    private String clientCharset;
    private String clientName = System.getProperties().getProperty("user.name");
    /**
     * 局域网ip
     */
    private String clientIpOfLocal;
    private String clientIpOfWlan;
    private String clientIpOfProxy;
    private String clientPort;
    private String osVersion = System.getProperties().getProperty("os.version");
    private String osName = System.getProperties().getProperty("os.name");
    private String osArch = System.getProperties().getProperty("os.arch");

    private KernelNode() {
    }

    @SneakyThrows
    public static KernelNode defaultJoin() {
        String username = System.getProperty("user.name");
        KernelNode kernelNode = new KernelNode().setUsername(username);
        //
        kernelNode.setClientIpOfWlan(NetUtil.getLocalhostStr());
        //
        kernelNode.setClientIpOfLocal(InetAddress.getLocalHost().getHostAddress());
        //kernelNode.setAddress(LocalCacheUtil.IpCache.get("local").orElse("获取ip异常"));
        return kernelNode.setOnline(false);
    }

    /**
     * 判断终端类型
     *
     * @return 判断结果
     */
    public boolean judgeDos() {
        return MatrixNodeType.dos_a.getDesc().equals(this.nodeType);
    }

    /**
     * beautifySelf
     *
     * @param message message
     * @return String
     */
    @SneakyThrows
    public Message beautifySelf(Message message) {
        this.content = message.getContent();
        //
        String nodeContent = JsonUtils.toJson(this);
        message.setContent(nodeContent);
        return message;
    }

    public boolean msgServerTransmitting(Message message) {
        try {
            this.getPrintWriter().println(JsonUtils.toJson(message));
            this.getPrintWriter().flush();
            log.debug("服务器消息推送[{}]", message);
            return true;
        } catch (Exception e) {
            /* 服务器先移除下线节点 */
            this.setOnline(false);
            return false;
        }
    }

    public boolean msgClientSend(Message message) {
        if (!this.online) {
            log.error("[{}]-节点离线-[{}]:{}", this.getNodeInfo(), message.getItemDesc(), message.getContent());
            return false;
        }
        try {
            log.debug("[{}]-发送消息[{}]:{}", this.getNodeInfo(), message.getItemDesc(), message.getContent());
            this.getPrintWriter().println(JsonUtils.toJson(message));
            this.getPrintWriter().flush();
            return true;
        } catch (Exception e) {
            log.error("[{}]-error with:[{}]-@-[{}]", this.getNodeInfo(), e.getMessage(), message, e);
            return false;
        }
    }

    /**
     * getClientInfo
     *
     * @return String
     */
    public String getNodeInfo() {
        String nodeInfo;
        nodeInfo = "~" + ("getAddress".contains("电信") ? "1" : "0")
                //+ "~" + StringUtils.rightPad(getServerIp(), 15)
                //+ "~" + StringUtils.rightPad(getClientIpOfLocal(), 15)
                //+ "~" + StringUtils.rightPad(getAddress(), 12)
                + "~" + StringUtils.rightPad(getClientName(), 12)
        ;
        return nodeInfo;
    }

    public String readLine() {
        try {
            return bufferedReader.readLine();
        } catch (Exception e) {
            log.debug("[{}]-读取异常-ERROR:[{}]", getNodeInfo(), e.getMessage(), e);
            return "";
        }
    }

    public boolean doQuit() {
        log.debug("[{}]-{}", this.getNodeInfo(), "quit");
        //移除节点
        this.setOnline(false);
        try {
            this.getServerSocket().close();
            this.getBufferedReader().close();
            this.getPrintWriter().close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
